package li.teng.joy.xcr.android;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.util.Enumeration;

import android.media.MediaRecorder;
import android.util.Log;

public class SsdpAgent {
	private ByteBuffer Buffer;
	MulticastSocket m_MulticastSocket = null;
	InetAddress group = null;
	public String rd_url;
	private DatagramChannel channel;
	String m_LocalIp;
	RecevMsg m_RecevMsgThread;
	boolean m_IsListening = false;
	public VideoParameters m_VideoParameters = new VideoParameters();
	public SsdpAgent(){
		try{
			group = InetAddress.getByName(Ssdp.SDDP_ADDRESS);
			m_MulticastSocket = new MulticastSocket();
		}catch(Exception ex){
			;
		}
	}
	public boolean isListening(){
		return m_IsListening;
	}
	
	public boolean startListen() {
		Log.e("XInput", "ssdp service start listen");
		try {
			channel = DatagramChannel.open();
			channel.configureBlocking(false);
			SocketAddress address = new InetSocketAddress(Ssdp.SDDP_PORT);
			DatagramSocket socket = channel.socket();
			socket.bind(address);
			try {
				Log.d("XInput", "ssdp service startListen bind ok");	
				m_RecevMsgThread = new RecevMsg();
				m_RecevMsgThread.start();
			} catch (Exception e) {
				Log.e("XInput", "ssdp service startListen bind failed");	
				return false;
			}
		} catch (IOException e) {
			return false;
		}
		m_IsListening = true;
		return true;
	}

	public void Stop(){
		Log.d("XInput", "ssdp service stop bind ok");
		m_RecevMsgThread.stopme();
		if(channel != null){
			Log.d("XInput", "ssdp service close socket");
			try{
				channel.close();
				Log.d("XInput", "ssdp service close socket ok");
				channel = null;
			}catch(Exception ex){
				Log.e("XInput", "ssdp service stop failed");
			}
		}
		m_IsListening = false;
	}
	
	class RecevMsg extends Thread {
		boolean flag;
		public void run() {
			ByteBuffer buff = ByteBuffer.allocate(1024);
			SocketAddress client = null;
			flag = true;
			Log.d("XInput", "ssdp start recv " );
			while (flag) {
				try {
					if ((client = channel.receive(buff)) != null) {
						buff.flip();
						Log.d("XInput", "recevMsg " + buff.limit());
						Ssdp obj = Ssdp.Parse(buff.array(), buff.limit());
						if (obj.messageType == MessageType.SearchRequest) {
							Ssdp ret = new Ssdp();
							ret.messageType = MessageType.SearchResponse;
							ret.ST = obj.ST;
							
							if(m_LocalIp != null)ret.Location = m_LocalIp + "?format=" + m_VideoParameters.m_Format + "&" +
																				"width=" + m_VideoParameters.m_PixWidth + "&" + 
																				"height=" + m_VideoParameters.m_PixHeight + "&" +
																				"framerate=" + m_VideoParameters.m_FrameRate + "&" + 
																				"model=" + android.os.Build.MODEL + "&" + 
																				"imei=" + m_VideoParameters.IMEI;
							ret.OSVersion = "windows/5.0";
							ret.ProductVersion = "stub/1.0";
							sendResponse(ret);
						}
						buff.clear();
					}
				} catch (Exception ex) {

				}
			}
		}
		
		public void stopme(){
			flag = false;
		}
	}

	public void sendResponse(Ssdp obj) {
		try {
			byte[] buffer = obj.GetCommandBytes();
			DatagramPacket data = new DatagramPacket(buffer,buffer.length,group,Ssdp.SDDP_PORT);
			m_MulticastSocket.send(data);
		} catch (Exception ex) {
			System.out.println("sendResponse failed\r\n" + ex.toString());
		}
	}
	
	public String GetLocalIp() {
	    try {
	        for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
	            NetworkInterface intf = en.nextElement();
	            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
	                InetAddress inetAddress = enumIpAddr.nextElement();
	                if (!inetAddress.isLoopbackAddress()) {
	                	m_LocalIp = inetAddress.getHostAddress().toString();
	                	return m_LocalIp;
	                }
	            }
	        }
	    } catch (SocketException ex) {
	        Log.e("XInput", ex.toString());
	    }
	    return null;
	}
}
